import { useState, useEffect } from 'react';
import Head from 'next/head';
import { 
  Upload, 
  Button, 
  Card, 
  Typography, 
  Radio, 
  List, 
  Tag, 
  Divider, 
  message, 
  Progress,
  Collapse,
  Alert,
  Switch
} from 'antd';
import { 
  InboxOutlined, 
  FileOutlined, 
  DeleteOutlined, 
  DownloadOutlined,
  CloudUploadOutlined,
  LaptopOutlined 
} from '@ant-design/icons';
import MainLayout from '../../components/layout/MainLayout';
import axios from 'axios';
import JSZip from 'jszip';
import styles from '../../styles/ToolDetail.module.css';

const { Title, Paragraph, Text } = Typography;
const { Dragger } = Upload;
const { Panel } = Collapse;

// 定义大文件的阈值 (10MB)
const LARGE_FILE_THRESHOLD = 10 * 1024 * 1024;
// 总文件大小阈值 (50MB)
const TOTAL_SIZE_THRESHOLD = 50 * 1024 * 1024;

export default function FileCompress() {
  const [fileList, setFileList] = useState([]);
  const [compressLevel, setCompressLevel] = useState('medium');
  const [compressFormat, setCompressFormat] = useState('zip');
  const [isCompressing, setIsCompressing] = useState(false);
  const [progress, setProgress] = useState(0);
  const [resultUrl, setResultUrl] = useState('');
  const [processingMode, setProcessingMode] = useState('browser');
  const [autoSwitchMode, setAutoSwitchMode] = useState(true);
  const [totalSize, setTotalSize] = useState(0);
  const [hasLargeFile, setHasLargeFile] = useState(false);
  const [compressionResult, setCompressionResult] = useState({
    originalSize: 0,
    compressedSize: 0,
    compressionRatio: 0,
    savedSize: 0
  });
  
  // 监控文件列表，计算总大小和检测大文件
  useEffect(() => {
    let total = 0;
    let hasLarge = false;
    
    fileList.forEach(file => {
      total += file.size;
      if (file.size > LARGE_FILE_THRESHOLD) {
        hasLarge = true;
      }
    });
    
    setTotalSize(total);
    setHasLargeFile(hasLarge);
    
    // 如果开启自动切换且有大文件或总大小超过阈值，切换到服务器处理
    if (autoSwitchMode && (hasLarge || total > TOTAL_SIZE_THRESHOLD)) {
      setProcessingMode('server');
    }
  }, [fileList, autoSwitchMode]);
  
  const handleFileChange = (info) => {
    let fileList = [...info.fileList];
    
    // 限制最多上传10个文件
    fileList = fileList.slice(-10);
    
    setFileList(fileList);
  };
  
  const removeFile = (file) => {
    const index = fileList.indexOf(file);
    const newFileList = fileList.slice();
    newFileList.splice(index, 1);
    setFileList(newFileList);
  };
  
  const formatFileSize = (bytes) => {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  };
  
  const compressInBrowser = async () => {
    try {
      // 在前端使用JSZip压缩文件
      const zip = new JSZip();
      
      // 根据压缩级别设置压缩选项
      const compressionOptions = {
        level: compressLevel === 'low' ? 1 : compressLevel === 'medium' ? 5 : 9
      };
      
      // 将文件添加到zip
      for (let i = 0; i < fileList.length; i++) {
        const file = fileList[i].originFileObj;
        const fileData = await readFileAsArrayBuffer(file);
        zip.file(file.name, fileData, compressionOptions);
        
        // 更新进度
        setProgress(Math.round((i + 1) / fileList.length * 50));
      }
      
      // 生成zip
      const content = await zip.generateAsync({
        type: 'blob',
        compression: 'DEFLATE',
        compressionOptions: compressionOptions
      }, (metadata) => {
        setProgress(50 + Math.round(metadata.percent / 2));
      });
      
      // 创建下载链接
      const url = URL.createObjectURL(content);
      setResultUrl(url);
      setProgress(100);
      
      return {
        success: true,
        url: url,
        size: content.size,
        originalSize: totalSize
      };
    } catch (error) {
      console.error('浏览器压缩错误:', error);
      throw new Error('浏览器压缩文件失败: ' + error.message);
    }
  };
  
  const compressOnServer = async () => {
    try {
      // 准备所有文件的FormData
      const formData = new FormData();
      
      // 添加压缩选项
      formData.append('level', compressLevel);
      formData.append('format', compressFormat);
      
      // 添加文件
      fileList.forEach((file, index) => {
        formData.append('files', file.originFileObj);
        
        // 模拟上传进度
        setProgress(Math.round((index + 1) / fileList.length * 70));
      });
      
      // 调用服务器API
      const response = await axios.post('/api/file/compress-upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: (progressEvent) => {
          const percentCompleted = Math.round(
            (progressEvent.loaded * 70) / progressEvent.total
          );
          setProgress(percentCompleted);
        }
      });
      
      // 处理响应
      if (response.data.code === 200) {
        setProgress(100);
        return {
          success: true,
          url: response.data.data.downloadUrl,
          size: response.data.data.size,
          fileId: response.data.data.fileId,
          originalSize: totalSize
        };
      } else {
        throw new Error(response.data.message || '服务器压缩失败');
      }
    } catch (error) {
      console.error('服务器压缩错误:', error);
      throw new Error('服务器压缩文件失败: ' + (error.response?.data?.message || error.message));
    }
  };
  
  const handleCompress = async () => {
    if (fileList.length === 0) {
      message.warning('请先上传文件');
      return;
    }
    
    setIsCompressing(true);
    setProgress(0);
    setResultUrl('');
    
    try {
      let result;
      
      // 根据处理模式选择压缩方法
      if (processingMode === 'browser') {
        result = await compressInBrowser();
      } else {
        result = await compressOnServer();
      }
      
      if (result.success) {
        setResultUrl(result.url);
        
        // 计算压缩比率和节省的空间
        const originalSize = result.originalSize;
        const compressedSize = result.size;
        const savedSize = originalSize - compressedSize;
        const compressionRatio = ((savedSize / originalSize) * 100).toFixed(2);
        
        // 保存压缩结果信息
        setCompressionResult({
          originalSize,
          compressedSize,
          compressionRatio,
          savedSize
        });
        
        message.success('文件压缩完成');
      }
    } catch (error) {
      console.error('压缩错误:', error);
      message.error(error.message || '压缩过程中出错');
    } finally {
      setIsCompressing(false);
    }
  };
  
  const readFileAsArrayBuffer = (file) => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (e) => resolve(e.target.result);
      reader.onerror = (e) => reject(e);
      reader.readAsArrayBuffer(file);
    });
  };
  
  const handleDownload = () => {
    if (!resultUrl) return;
    
    if (processingMode === 'browser') {
      // 浏览器端处理：创建一个临时链接用于下载
      const link = document.createElement('a');
      link.href = resultUrl;
      link.download = `compressed.${compressFormat}`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    } else {
      // 服务器端处理：直接跳转到下载链接
      window.location.href = resultUrl;
    }
  };
  
  return (
    <MainLayout>
      <Head>
        <title>文件压缩 - 在线工具平台</title>
        <meta name="description" content="在线压缩文件，支持多种格式和压缩级别" />
      </Head>
      
      <div className="page-header">
        <Title>文件压缩</Title>
        <Paragraph>
          压缩您的文件以减小体积，支持多种压缩格式和压缩级别
        </Paragraph>
      </div>
      
      <Card className="upload-card">
        <Dragger 
          fileList={fileList}
          onChange={handleFileChange}
          beforeUpload={() => false}
          multiple={true}
          showUploadList={false}
        >
          <p className="ant-upload-drag-icon">
            <InboxOutlined />
          </p>
          <p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
          <p className="ant-upload-hint">
            支持单个或批量上传，每次最多上传10个文件
          </p>
        </Dragger>
      </Card>
      
      {fileList.length > 0 && (
        <>
          <div className="file-list-container">
            <Divider orientation="left">已选文件</Divider>
            <List
              bordered
              dataSource={fileList}
              renderItem={file => (
                <List.Item
                  actions={[
                    <Button 
                      key="delete" 
                      type="text" 
                      danger 
                      icon={<DeleteOutlined />}
                      onClick={() => removeFile(file)}
                    />
                  ]}
                >
                  <List.Item.Meta
                    avatar={<FileOutlined />}
                    title={
                      <>
                        {file.name}
                        {file.size > LARGE_FILE_THRESHOLD && (
                          <Tag color="orange" style={{ marginLeft: 8 }}>大文件</Tag>
                        )}
                      </>
                    }
                    description={formatFileSize(file.size)}
                  />
                </List.Item>
              )}
            />
            <div style={{ marginTop: 8, textAlign: 'right' }}>
              <Text>总大小: {formatFileSize(totalSize)}</Text>
              {totalSize > TOTAL_SIZE_THRESHOLD && (
                <Tag color="orange" style={{ marginLeft: 8 }}>
                  超过推荐大小
                </Tag>
              )}
            </div>
          </div>
          
          {(hasLargeFile || totalSize > TOTAL_SIZE_THRESHOLD) && autoSwitchMode && (
            <Alert
              message="大文件提示"
              description="检测到大文件或大量文件，已自动切换到服务器处理模式以获得更好的性能。"
              type="info"
              showIcon
              style={{ marginTop: 16, marginBottom: 16 }}
            />
          )}
        </>
      )}
      
      <Card className="options-card" title="压缩选项">
        <div className="option-row">
          <div className="option-label">压缩级别:</div>
          <Radio.Group value={compressLevel} onChange={e => setCompressLevel(e.target.value)}>
            <Radio.Button value="low">低 (快速)</Radio.Button>
            <Radio.Button value="medium">中 (平衡)</Radio.Button>
            <Radio.Button value="high">高 (最小体积)</Radio.Button>
          </Radio.Group>
        </div>
        
        <div className="option-row">
          <div className="option-label">压缩格式:</div>
          <Radio.Group value={compressFormat} onChange={e => setCompressFormat(e.target.value)}>
            <Radio.Button value="zip">ZIP</Radio.Button>
            <Radio.Button value="rar" disabled={processingMode !== 'server'}>RAR</Radio.Button>
            <Radio.Button value="7z" disabled={processingMode !== 'server'}>7Z</Radio.Button>
          </Radio.Group>
          {processingMode !== 'server' && (
            <Text type="secondary" style={{ marginLeft: 16 }}>
              浏览器模式仅支持ZIP格式
            </Text>
          )}
        </div>
        
        <div className="option-row">
          <div className="option-label">处理模式:</div>
          <Radio.Group 
            value={processingMode} 
            onChange={e => setProcessingMode(e.target.value)}
            buttonStyle="solid"
          >
            <Radio.Button value="browser">
              <LaptopOutlined /> 浏览器端
            </Radio.Button>
            <Radio.Button value="server">
              <CloudUploadOutlined /> 服务器端
            </Radio.Button>
          </Radio.Group>
          <div style={{ marginLeft: 16, display: 'inline-flex', alignItems: 'center' }}>
            <Switch 
              checked={autoSwitchMode} 
              onChange={setAutoSwitchMode} 
              size="small" 
            />
            <Text type="secondary" style={{ marginLeft: 8 }}>
              自动切换模式
            </Text>
          </div>
        </div>
      </Card>
      
      <div className="action-container">
        <Button 
          type="primary" 
          size="large" 
          onClick={handleCompress}
          loading={isCompressing}
          disabled={fileList.length === 0}
          block
        >
          开始压缩
        </Button>
      </div>
      
      {isCompressing && (
        <div className="progress-container">
          <Progress percent={progress} status="active" />
          <Text>正在{processingMode === 'browser' ? '压缩' : '上传并压缩'}文件，请稍候...</Text>
        </div>
      )}
      
      {resultUrl && (
        <div className="result-container">
          <Alert
            message="压缩完成"
            description={`您的文件已成功压缩，点击下方按钮${processingMode === 'browser' ? '下载' : '从服务器下载'}压缩文件。`}
            type="success"
            showIcon
          />
          
          <Card 
            title="压缩结果统计" 
            className={styles['compression-stats-card']}
            style={{ marginTop: 16 }}
          >
            <div className={styles['stats-container']}>
              <div className={styles['stat-item']}>
                <Text strong>原始大小：</Text>
                <Text>{formatFileSize(compressionResult.originalSize)}</Text>
              </div>
              <div className={styles['stat-item']}>
                <Text strong>压缩后大小：</Text>
                <Text>{formatFileSize(compressionResult.compressedSize)}</Text>
              </div>
              <div className={styles['stat-item']}>
                <Text strong>节省空间：</Text>
                <Text>{formatFileSize(compressionResult.savedSize)}</Text>
              </div>
              <div className={styles['stat-item']}>
                <Text strong>压缩率：</Text>
                <Text>{compressionResult.compressionRatio}%</Text>
                <Progress 
                  percent={parseFloat(compressionResult.compressionRatio)} 
                  size="small" 
                  status="success"
                  style={{ marginLeft: 8, width: 100 }}
                />
              </div>
            </div>
          </Card>
          
          <Button 
            type="primary" 
            icon={<DownloadOutlined />}
            onClick={handleDownload}
            size="large"
            style={{ marginTop: 16 }}
          >
            下载压缩文件
          </Button>
        </div>
      )}
      
      <Divider />
      
      <Collapse className="help-container">
        <Panel header="使用说明" key="1">
          <Paragraph>
            <ol>
              <li>点击上传区域或将文件拖拽到上传区域选择要压缩的文件</li>
              <li>选择压缩级别和压缩格式</li>
              <li>选择处理模式（浏览器端或服务器端）</li>
              <li>点击"开始压缩"按钮开始压缩过程</li>
              <li>压缩完成后，点击"下载"按钮下载压缩文件</li>
            </ol>
          </Paragraph>
        </Panel>
        <Panel header="浏览器端与服务器端的区别" key="2">
          <Paragraph>
            <strong>浏览器端处理:</strong>
            <ul>
              <li>适合小文件（&lt;10MB）和少量文件</li>
              <li>无需上传文件，处理速度快</li>
              <li>受浏览器内存限制，大文件可能失败</li>
              <li>仅支持ZIP格式</li>
            </ul>
            <strong>服务器端处理:</strong>
            <ul>
              <li>适合大文件和多个文件</li>
              <li>需要先上传文件，总处理时间较长</li>
              <li>可处理更大的文件（最大100MB）</li>
              <li>支持更多压缩格式（ZIP、RAR、7Z）</li>
            </ul>
          </Paragraph>
        </Panel>
        <Panel header="常见问题" key="3">
          <Paragraph>
            <strong>Q: 支持压缩多大的文件？</strong><br />
            A: 浏览器端模式建议文件不超过10MB，服务器端模式支持最大100MB的文件。<br /><br />
            
            <strong>Q: 为什么在浏览器模式下只能使用ZIP格式？</strong><br />
            A: 由于浏览器的限制，前端JavaScript库只支持ZIP格式。RAR和7Z格式需要服务器后端支持。<br /><br />
            
            <strong>Q: 压缩文件安全吗？</strong><br />
            A: 是的，浏览器端处理时，文件不会上传到服务器。服务器端处理时，文件会加密传输并在处理后自动删除。
          </Paragraph>
        </Panel>
      </Collapse>
    </MainLayout>
  );
} 